#include <stdio.h>
#include <stdlib.h>
#include "slave.h"
#include <assert.h>
#include "args.h"
#include "aceMesh_utils.h"
#include "aceMesh_task.h"
#include "aceMesh_runtime.h"
#include "helper_slave.h"

__thread_local volatile int helper_init_done=0;
// __thread_local_fix int construct_end=0;
__thread_local_fix int construct_end=0;
// volatile int close_helper=0;
unsigned long close_helper[64]={0};
extern __thread_local int helper_exited[64];
__thread_local_fix int over=0;
// __thread_local int helper_exited = 1;
volatile int helper_finished[64]={0};
// __uncached volatile int slave_init_done=0;
__thread_local_fix struct slave_help_buff slave_buffer[NT];
// extern volatile void* need_spawn_subtasks[NEED_SPAWN_SUBSIZE];
// extern __thread_local_fix spawn_subtask_num;
#define remote_ldm(coreid,ldm_var) ((unsigned long)&ldm_var | ((unsigned long)coreid << 20 ) |(1ULL << 45))
#ifdef ACEMESH_GRAPH_BUILD_PROFILING
extern unsigned long buil_prof[N_BUILD_PROF];
#endif
void init_slave_buffer(int myid)
{
    int i;
    for(i=0;i<NT;i++){
       slave_buffer[i].head=0;
       slave_buffer[i].tail=0;
    }
}
void add_succ(struct DataAccess *succ_access, struct DataAccess *pre_access)
{
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    unsigned long add_succ_start=rtc();
#endif
     //printf("tbl任务类型%dtblDA地址%p任务地址%ptbl任务地址%p,\n",tbl->data_access->_type,tbl->data_access,data_access->_originator,tbl->data_access->_originator);
    if(pre_access!=NULL){
        if(pre_access->_type==IN && succ_access->_type==IN && pre_access->_accessFlags==SATISFIED){   //识别第一层，前驱是已经就绪的R，新增加剧的R也是自然就绪的，仅连接不阻塞
            slave_set_access_state(SATISFIED, &(succ_access->_accessFlags));
            // succ_access->_accessFlags=SATISFIED;
            slave_set_unblock_Successor(pre_access,succ_access); //R1-R2,R1是top，R2为ready
           asm volatile ("memb\n");
					 // printf("不阻塞的前驱子任务%p,后继子任务%p\n",predata_access->_originator,data_access->_originator);
         }else { // 以上三个条件，任一不满足，都说明存在实际的依赖（R-W，W-R，W-W，W-R-R），必须修改引用计数
            slave_setSuccessor(pre_access,succ_access);   
						asm volatile ("memb\n");
           // printf("前驱子任务%p,后继子任务%p\n",predata_access->_originator,data_access->_originator); 
        }   

    }else{
        if(succ_access->_type==IN){ //该地址没有前驱，且类型为读，则设置addr.top=true
            slave_set_access_state(1, &(succ_access->top));
            // succ_access->top=true;
						asm volatile ("memb\n");
       // printf("设置%p为top%d\n",data_access,data_access->top);
        }
        slave_set_access_state(SATISFIED, &(succ_access->_accessFlags));
        // succ_access->_accessFlags=SATISFIED;
    }
    //printf("设置succ\n");
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    buil_prof[SUB_ADD_SUCC]+=(rtc()-add_succ_start);
#endif
}
inline struct new_slave_table_item * new_get_collision_buffer_item(struct new_slave_table *addresses)
{
    //printf("addresses->col_idx %d\n",addresses->col_idx );
    assert(addresses->col_idx  < COLLISION_BUF_SIZE);
       if (addresses->col_idx >= COLLISION_BUF_SIZE) {
        int i;
        int empty = 0;
        for (i = 0; i < SLAVE_TBL_SIZE; i++) {
            if (addresses->items[i].data_addr == NULL) {
                empty++;
            }
        }
        printf("empty rate: %f\n", (float)empty / SLAVE_TBL_SIZE);
        fflush(stdout);
        // assert(0);
    }
   struct new_slave_table_item * item = &(addresses->col_items[addresses->col_idx]);
    addresses->col_idx++;
    return item;
}
void helper_reigister_access(struct slave_helper_item *item){
		//获取依赖分析需要的各种信息
		void *address=item->item_address;
		unsigned long hash_value=item->item_hash;
		struct DataAccess *access=item->item_access;
		int id=item->item_id;

		struct DataAccess *predecessor=NULL;
		int tbl_idx = 0;
		//当前任务，以及当前复合任务
		aceMesh_task *cur_task=access->_originator;
		aceMesh_task *parent=slave_getparent(&(cur_task->task_base));
		//printf("地址%p,子任务%p,父任务%p\n",address,cur_task,parent);
		//复合任务、及对应哈希表
		struct TaskDataAccesses *parentAccessStruct = slave_getDataAccesses(&(parent->task_base));
		volatile struct new_slave_table *addresses = parentAccessStruct->_subaccessBottomMap;
		//unsigned long hash_value = (unsigned long)address * HASH_MULT_VALUE;
			tbl_idx = ((hash_value) >> 44) & 0xffff; ////取高20位(高位的变化更大)中的低16位，65536
		// printf("%p更新DA地址%ptbl地址%p,\n",tbl->data_access,access->_originator,tbl->data_access->_originator);
		if (addresses->items[tbl_idx].data_addr == address) {  //哈希表存在地址
					predecessor=addresses->items[tbl_idx].data_access;
						slave_add_succ(access, predecessor);
							addresses->items[tbl_idx].data_access=access; //更新哈希表
							asm volatile ("memb\n");

				}
				else if (addresses->items[tbl_idx].data_addr == NULL) { //哈希表不存在此地址
						predecessor=addresses->items[tbl_idx].data_access;
						addresses->items[tbl_idx].data_addr = address;
						slave_add_succ(access, predecessor);
						addresses->items[tbl_idx].data_access=access; //更新哈希表
						asm volatile ("memb\n");

				}
				else {
						//printf("哈希冲突%p\n",address);
						struct new_slave_table_item * col_item = NULL;
						struct new_slave_table_item * temp = &(addresses->items[tbl_idx]);
						while (temp->succ != NULL) { 
								//struct new_slave_table_item *temp_item=NULL;
								//temp_item=temp->succ;
								if (temp->succ->data_addr == address) {  
										//slave_new_update_hashitem(access, temp->succ);
										
										predecessor=temp->succ->data_access;
										slave_add_succ(access, predecessor);
										temp->succ->data_access=access; //更新哈希表
										asm volatile ("memb\n");
										goto update_complete;
								}
								temp = temp->succ;   
						
						}      
						col_item = new_get_collision_buffer_item(addresses);    
						temp->succ = col_item;
						col_item->data_addr = address;
						//slave_new_update_hashitem(access, col_item);
						predecessor=col_item->data_access;
						slave_add_succ(access, predecessor); //依赖边追加和前驱计数更新
						col_item->data_access=access; //更新哈希表
				update_complete:
						;
			
				}
			// printf("子任务前驱计数task%p,precount:%d\n",cur_task,cur_task->task_base._predecessorCount);
}
__thread_local_fix int index_id=0;
/*void get_elem_from_build_and_analysis(int builder_finished){
	  struct slave_help_buff* self=NULL;
    int local_head=0,i;
		int id=_MYID;
    struct slave_helper_item *buff_item=NULL;
		for(i=0; i<NT; i++){ //一对一模式，虽然轮转64个buffer，但取的只有buffer1
    self=&slave_buffer[(i + index_id)%NT];  //当前从核的环形队列
		int buffer_id=(i + index_id)%NT;
		local_head=self->head;
		//printf("****接收****头指针%d,尾指针%d\n",local_head,self->tail);
		if(self->tail==local_head){//当从核环形队列没有元素，则查找下一个队列
		// if(builder_finished&&(_MYID==8)) {  //没有元素且没有新任务的情况下，结束helper，转为计算线程
		// 		//printf("****接收****头指针%d,尾指针%d\n",local_head,self->tail);
		// 		helper_finished[_MYID] = 1;  //从核8结束
		// 		printf("helepr_buffer结束%d\n",_MYID);
		// 	}
			  //printf("从核%d队列为空\n",(i + index_id)%NT);
		    continue;
		}
		buff_item=&(self->base[local_head]);  //接收建边需要的数据流地址信息
		void *address=buff_item->item_address;
		if(address==NULL){
			//printf("从核%d取到%d结束\n",buffer_id,local_head);
			helper_finished[buffer_id] == 1;
		}else{
		//printf("从核%d队列不为空\n",(i + index_id)%NT);
		slave_helper_reigister_access(buff_item); //依赖分析，建边
    self->head=(local_head+1)%HELPER_BUFF_SIZE;  //head指针+1，取下一个元素
		}
		index_id++;
		}
        //printf("%ld,",temp_value);

}*/
void worker_help_func()
{
	// printf("%dhelper轮询开始\n",_MYID);
    // int i;
    // int main_finished = 0;
   //init_slave_buffer();  //从核初始化
	 //printf("_MYID %dslave_init_done ok\n",_MYID);
    // asm volatile ("memb\n");
    // helper_init_done = 1;  //从核初始化完毕
		int builder_finished = 0;

		//  helper_exited[_MYID]=0;
		// helper_exited=0;
		
		int close=0;
		int exit=0;
    struct slave_helper_item * buff_item=NULL;    
    // while (close_num!=64) { //一直轮转，至64个buffer全部为空
    while (!close) { //一直轮转，至64个buffer全部为空

		// if(construct_end){
		// 	//printf("****从核%d结束\n",_MYID);
		// 	builder_finished=1;
		// }
		close_helper[_MYID]=&close;
		struct slave_help_buff* self=NULL;
    int local_head=0,i;
		int id=_MYID;
    struct slave_helper_item *buff_item=NULL;
		for(i=0; i<NT; i++){ //一对一模式，虽然轮转64个buffer，但取的只有buffer1
    self=&slave_buffer[(i + index_id)%NT];  //当前从核的环形队列
		int buffer_id=(i + index_id)%NT;
		local_head=self->head;
		//printf("****接收****头指针%d,尾指针%d\n",local_head,self->tail);
		if(self->tail==local_head){//当从核环形队列没有元素，则查找下一个队列
		// if(builder_finished&&(_MYID==8)) {  //没有元素且没有新任务的情况下，结束helper，转为计算线程
		// 		//printf("****接收****头指针%d,尾指针%d\n",local_head,self->tail);
		// 		helper_finished[_MYID] = 1;  //从核8结束
		// 		printf("helepr_buffer结束%d\n",_MYID);
		// 	}
			  //printf("从核%d队列为空\n",(i + index_id)%NT);
		    continue;
		}
		buff_item=&(self->base[local_head]);  //接收建边需要的数据流地址信息
		// void *address=buff_item->item_address;
		int hash=buff_item->item_hash;
		if(hash==1){ //buffer接收到终止消息,等于1是因为终止消息的hash为1
			// printf("从核%d取到%d结束\n",buffer_id,local_head);
			//helper_exited[buffer_id]=1;
			int *exit_signal=remote_ldm(buffer_id, helper_exited[buffer_id]);
			*exit_signal= 1;
			//printf("从核%dbuffer%d结束%d\n",_MYID,buffer_id,helper_exited[buffer_id]);
#ifdef DEBUG_PBH
			printf("从核%dbuffer%d结束\n",_MYID,buffer_id);
#endif

		}else{
		//printf("从核%d队列不为空\n",(i + index_id)%NT);
		// printf("****接收bufferid%d****头指针%d,尾指针%d\n",buffer_id,local_head,self->tail);
		slave_helper_reigister_access(buff_item); //依赖分析，建边
		}
		self->head=(local_head+1)%HELPER_BUFF_SIZE;  //head指针+1，取下一个元素
		index_id++;
		}
       // slave_get_elem_from_build_and_analysis(builder_finished);
			
		// 		close_num=0;
		// 	for (i = 0; i < 64; i++) {
		// 			if (helper_finished[i] == 1) { //helper finish
		// 			close_num++;
		// 						printf("终止个数%d\n",close_num);
		// 					//break;
		// 			}
		// }
				//else{
				// 	break;
				// }
       
    }   
		//helper_exited=1;
#ifdef DEBUG_PBH
	 printf("%dhelper轮询终止\n",_MYID);
#endif
		
}
